package com.ship.dispatch.service.orderPay.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ship.common.core.enums.OrderStatus;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.common.business.service.impl.BaseServiceImpl;
import com.ship.common.core.utils.BeanCopyUtils;
import com.ship.dispatch.bean.orderPay.SpFundManage;
import com.ship.dispatch.bean.orderPay.SpFundManageDetail;
import com.ship.dispatch.bean.orderPay.SpFundPayManageDetail;
import com.ship.dispatch.bean.orderPay.SpPaymentOrder;
import com.ship.dispatch.bo.orderPay.SpFundManageDetailBo;
import com.ship.dispatch.bo.orderPay.SpFundManageDetailRq;
import com.ship.dispatch.bo.orderPay.SpFundManagePageBo;
import com.ship.dispatch.bo.orderPay.SpFundManageUpdateBo;
import com.ship.dispatch.mapper.orderPay.SpFundManageDetailMapper;
import com.ship.dispatch.service.impl.ShipBaseServiceImpl;
import com.ship.dispatch.service.orderPay.SpFundManageDetailService;
import com.ship.dispatch.service.orderPay.SpFundManageService;
import com.ship.dispatch.service.orderPay.SpFundPayManageDetailService;
import com.ship.dispatch.service.orderPay.SpPaymentOrderService;
import com.ship.common.security.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SpFundManageDetailServiceImpl extends BaseServiceImpl<SpFundManageDetailMapper, SpFundManageDetail>
        implements SpFundManageDetailService {

    @Autowired
    @Lazy
    private SpFundManageService spFundManageService;

    @Autowired
    @Lazy
    private SpPaymentOrderService spPaymentOrderService;

    @Autowired
    private SpFundPayManageDetailService spFundPayManageDetailService;

    /**
     * 统计支付次数
     * @return
     */
    @Override
    public Integer getPayNumberTotal(){
        Integer orderNum =0;
        SpFundManageDetailBo detailBo = new SpFundManageDetailBo();
        List<SpFundManageDetail> exportList = this.getExportManageDetail(detailBo);
        for (SpFundManageDetail detail : exportList) {
            if(StringUtils.isNotBlank(detail.getCorporateName())){
                orderNum += this.getOrderCountByCorporateName(detail.getCorporateName());
            }
        }
        return orderNum;
    }

    /**
     * 统计账户余额
     * @return
     */
    @Override
    public BigDecimal getAccountBalanceTotal(){
        BigDecimal total = BigDecimal.ZERO;
        List<String> corporateNames = this.getBaseMapper().getCorporateNames();
        if(null != corporateNames && corporateNames.size()>0){
            for (String corporateName : corporateNames) {
                //某公司国贸最新信息
                SpFundManageDetail fundManageDetail1 = this.getBaseMapper().getCorporateTradeInfo(1,corporateName);
                if(null != fundManageDetail1 && fundManageDetail1.getAccountBalance() != null){
                    total = total.add(fundManageDetail1.getAccountBalance());
                }
                //某公司新贸最新信息
                SpFundManageDetail fundManageDetail2 = this.getBaseMapper().getCorporateTradeInfo(2,corporateName);
                if(null != fundManageDetail2 && fundManageDetail2.getAccountBalance() != null){
                    total = total.add(fundManageDetail2.getAccountBalance());
                }
            }
        }
        return total;
    }

    /**
     * 船舶代理平均费用
     * @return
     */
    @Override
    public BigDecimal getShipAgencyAverageBalance(){
        BigDecimal averageBalance = BigDecimal.ZERO;
        List<SpFundManageDetail> detailsNew = new ArrayList<>();
        List<SpFundManageDetail> details = this.getBaseMapper().getShipAgencyAverageBalance();
        if(null != details && details.size()>0){
            Map<String,List<SpFundManageDetail>> detailMap = details.stream().filter(d->StringUtils.isNotBlank(d.getCorporateName())).collect(Collectors.groupingBy(SpFundManageDetail::getCorporateName));
            for (String detail : detailMap.keySet()) {
                List<SpFundManageDetail> spFundManageDetails = detailMap.get(detail);
                if(null != spFundManageDetails && spFundManageDetails.size()>0){
                    List<SpFundManageDetail> internatTrades = spFundManageDetails.stream().filter(f->null!=f.getTradeBody() && f.getTradeBody().equals(1)).sorted((o1,o2)->o2.getCreateDate().compareTo(o1.getCreateDate())).collect(Collectors.toList());
                    if(null != internatTrades && internatTrades.size()>0){
                        detailsNew.add(internatTrades.get(0));
                    }
                    List<SpFundManageDetail> newTrades = spFundManageDetails.stream().filter(f->null!=f.getTradeBody() && f.getTradeBody().equals(2)).sorted((o1,o2)->o2.getCreateDate().compareTo(o1.getCreateDate())).collect(Collectors.toList());
                    if(null != newTrades && newTrades.size()>0){
                        detailsNew.add(newTrades.get(0));
                    }
                }
            }
            if(detailsNew.size()>0){
                BigDecimal total = detailsNew.stream().filter(d->null != d.getAccountBalance()).map(SpFundManageDetail::getAccountBalance)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                averageBalance = total.divide(new BigDecimal(details.size()),2, BigDecimal.ROUND_HALF_UP);
            }
        }
        return averageBalance;
    }

    @Override
    public JsonResult<SpFundManageDetail> baseStatistics(String corporateName) {
        SpFundManageDetail manageDetail = this.baseMapper.selectOne(
                new LambdaQueryWrapper<SpFundManageDetail>()
                        .eq(SpFundManageDetail::getCorporateName,corporateName)
                        .orderByDesc(SpFundManageDetail::getCreateDate)
                        .last("limit 1")
        );
        if(manageDetail == null){
            return JsonResult.failed("基础账户信息异常！");
        }
        manageDetail.setFundOrderNumber(this.getOrderCountByCorporateName(corporateName));
        return JsonResult.success(manageDetail);
    }

    @Override
    public JsonResult getPage(SpFundManage dto) {
        SpFundManagePageBo pageBo = new SpFundManagePageBo();
        BeanCopyUtils.copy(dto,pageBo);
        pageBo.setCurrent(dto.getPageNum());
        pageBo.setSize(dto.getPageSize());
        Page<SpFundManage> basePage = this.baseMapper.getManagePage(pageBo);
        com.ship.common.core.base.Page resultPage = new com.ship.common.core.base.Page();
        resultPage.setPageNum(dto.getPageNum());
        resultPage.setPageSize(dto.getPageSize());
        resultPage.setTotal(basePage.getTotal());
        resultPage.setList(basePage.getRecords());
        return JsonResult.success(resultPage);
    }



    @Override
    public JsonResult batchUpdate(SpFundManageUpdateBo dto) {
        if(dto.getIds() == null || dto.getIds().size() == 0){
            return JsonResult.failed("需要变更的信息ID不能为空！");
        }
        if(dto.getOrderStatus() == null){
            return JsonResult.failed("变更的状态不能为空");
        }
        List<SpFundManage> fundManages = spFundManageService.getBaseMapper().selectList(
                new LambdaQueryWrapper<SpFundManage>()
                        .in(SpFundManage::getId,dto.getIds())
        );
        List<SpFundManage> saveList = new LinkedList<>();
        List<SpPaymentOrder> orderSaveList = new LinkedList<>();
        for (SpFundManage fundManage : fundManages) {
            if(fundManage.getOrderStatus().intValue() >= dto.getOrderStatus()){
                continue;
            }
            fundManage.setOrderStatus(dto.getOrderStatus());
            if(dto.getOrderStatus().intValue() == 3){
                fundManage.setAccountBalance(BigDecimal.ZERO);
            }
            //同步更新对应支付订单的状态
            SpPaymentOrder order = spPaymentOrderService.getBaseMapper().selectOne(
                    new LambdaQueryWrapper<SpPaymentOrder>()
                    .eq(SpPaymentOrder::getPayOrderNumber,fundManage.getPayOrderNumber())
                    .last("limit 1")
            );
            if(order != null){
                order.setOrderStatus(dto.getOrderStatus());
                orderSaveList.add(order);
            }
            saveList.add(fundManage);
        }
        if(saveList.size() > 0){
            spFundManageService.updateBatchById(saveList);
        }
        if(orderSaveList.size() > 0){
            spPaymentOrderService.updateBatchById(orderSaveList);
        }
        return JsonResult.success();
    }

    @Override
    @Transactional
    public JsonResult balanceUpdate(SpFundManageUpdateBo dto) {
        if(StringUtils.isBlank(dto.getCorporateName())
                || dto.getAccountBalance() == null || StringUtils.isBlank(dto.getAccountEditBalanceRemark())){
            return JsonResult.failed("公司名称、更改后的余额、备注不能为空！");
        }
        SpFundManageDetail manageDetail = this.baseMapper.selectOne(
                new LambdaQueryWrapper<SpFundManageDetail>()
                        .eq(SpFundManageDetail::getCorporateName,dto.getCorporateName())
                        .orderByDesc(SpFundManageDetail::getCreateDate)
                        .last("limit 1")
        );
        if(manageDetail == null){
            return JsonResult.failed("基础账户信息异常！");
        }

        //付款信息
        SpFundManage fundManage = new SpFundManage();
        fundManage.setAccountInitialBalance(manageDetail.getAccountBalance());
        fundManage.setAccountBalance(dto.getAccountBalance());
        fundManage.setPayAmount(null);
        fundManage.setPaidAmount(null);
        fundManage.setOrderStatus(OrderStatus.PAID.getCode());
        fundManage.setCreateDate(new Date());
        fundManage.setCreateBy(SecurityUtils.getUsername());
        fundManage.setAccountEditBalanceRemark(dto.getAccountEditBalanceRemark());
        fundManage.setAccountEditBalancePath(dto.getAccountEditBalancePath());
        spFundManageService.save(fundManage);

        //账户余额信息
        SpFundManageDetail saveManageDetail = new SpFundManageDetail();
        BeanCopyUtils.copy(manageDetail,saveManageDetail);
        saveManageDetail.setId(null);
        saveManageDetail.setCreateDate(new Date());
        saveManageDetail.setCreateBy(SecurityUtils.getUsername());
        saveManageDetail.setAccountInitialBalance(fundManage.getAccountInitialBalance());
        saveManageDetail.setAccountBalance(fundManage.getAccountBalance());
        saveManageDetail.setFundManageId(fundManage.getId());
        saveManageDetail.setIsBalanceRecharge("1");
        this.save(saveManageDetail);

        //更新账户余额变更记录
        SpFundPayManageDetail spFundPayManageDetail = new SpFundPayManageDetail();
        spFundPayManageDetail.setPayNumber(dto.getAccountBalance());
        spFundPayManageDetail.setTradeBody(saveManageDetail.getTradeBody());
        spFundPayManageDetail.setCorporateName(saveManageDetail.getCorporateName());
        spFundPayManageDetail.setAccountBalance(saveManageDetail.getAccountBalance());
        spFundPayManageDetail.setCreateTime(new Date());
        spFundPayManageDetailService.save(spFundPayManageDetail);
        return JsonResult.success();
    }

    @Override
    public List<SpFundManage> getList(SpFundManage dto) {
        return this.baseMapper.getList(dto);
    }

    @Override
    public Integer getOrderCountByCorporateName(String corporateName) {
        Long count =  this.getBaseMapper().selectList(new LambdaQueryWrapper<SpFundManageDetail>()
                .eq(SpFundManageDetail::getCorporateName,corporateName)
        ).stream().map(p->p.getFundManageId()).distinct().count();
        return count.intValue();
    }

    @Override
    public PageInfo<SpFundManageDetail> getManageDetailPage(SpFundManageDetailBo dto){
        SpFundManageDetailRq spFundManageDetailRq = new SpFundManageDetailRq();
        BeanUtils.copyProperties(dto,spFundManageDetailRq);
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        List<SpFundManageDetail> detailList = this.baseMapper.getManageDetailPage(spFundManageDetailRq);
        PageInfo<SpFundManageDetail> pageInfo = new PageInfo<>(detailList);
        return pageInfo;
    }

    @Override
    public List<SpFundManageDetail> getExportManageDetail(SpFundManageDetailBo dto){
        List<SpFundManageDetail> list = this.baseMapper.getExportManageDetail(dto);
        return list;
    }
}
